package com.zzzy.cont.service.mycon;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzzy.common.enums.YesOrNoEnum;
import com.zzzy.common.exception.BusinessException;
import com.zzzy.common.exception.WarningException;
import com.zzzy.common.util.*;
import com.zzzy.cont.common.enums.ConOperateEnum;
import com.zzzy.cont.common.enums.ConStatusEnum;
import com.zzzy.cont.dao.entity.Contract;
import com.zzzy.cont.vo.contract.my.ConAddReq;
import com.zzzy.cont.vo.contract.my.ConUpdateReq;
import com.zzzy.framework.common.util.SecurityUtils;
import com.zzzy.framework.dto.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;

@Service
public class MyConDraftService extends MyConService {

    public String createConNo() {
        String conNo = "GW" + LocalDateUtils.getDateStr(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        while (checkIsExistConNo(conNo)){
            //与现有合同编号重复时，重新生成
            conNo = "GW" + LocalDateUtils.getDateStr(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        }
        return conNo;
    }

    @Transactional
    public Long addCon(ConAddReq addReq) {
        validateForAddFile(addReq);
        Long conId = doAddCon(addReq);
        //添加合同活动记录
        conActivityNoteService.addSysNote(conId, ConOperateEnum.ADD);
        return conId;
    }

    private Long doAddCon(ConAddReq addReq) {
        Contract contract = CglibBeanCopierUtil.copy(addReq, Contract.class);
        LocalDateTime dateNow = LocalDateTime.now();
        contract.setCreateTime(dateNow);
        contract.setUpdateTime(dateNow);
        contract.setStatus(ConStatusEnum.DRAFT.getValue());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        contract.setUserId(loginUser.getId());
        contract.setUserName(loginUser.getNickName());
        contract.setOperatorId(loginUser.getId());
        contract.setOperatorName(loginUser.getNickName());
        baseMapper.insert(contract);
        if (Objects.nonNull(addReq.getTemplateId())){
            conFileService.addConFileByTemplateId(contract.getId(), addReq.getTemplateId());
        } else {
            conFileService.addConFileByUploadFile(contract.getId(), addReq.getConFile());
        }
        return contract.getId();
    }

    private void validateForAddFile(ConAddReq addReq) {
        if (checkIsExistConNo(addReq.getConNo())) {
            throw new WarningException("当前文件编号已被占用，请更重新输入或自动生成");
        }
        if (Objects.isNull(addReq.getTemplateId()) && Objects.isNull(addReq.getConFile())) {
            throw new WarningException("请选择文件模板或上传合同文件");
        }
        if (YesOrNoEnum.YES.getValue().equals(addReq.getHasPeriod())
                && (Objects.isNull(addReq.getBeginPeriodTime()) || Objects.isNull(addReq.getEndPeriodTime()))){
            throw new WarningException("固定期限合同,期限开始时间与结束时间不能为空");
        }
        if (Objects.nonNull(addReq.getConFile())) {
            String filename = addReq.getConFile().getOriginalFilename();
            byte[] byteFileBlob;
            try {
                byteFileBlob = addReq.getConFile().getBytes();
            } catch (IOException e) {
                throw new BusinessException("文件读取错误");
            }
            String fileType = filename.substring(filename.lastIndexOf(".") +1);
            if (!FileUtil.DOC.equalsIgnoreCase(fileType) && !FileUtil.DOCX.equalsIgnoreCase(fileType) && !FileUtil.PDF.equalsIgnoreCase(fileType)){
                throw new BusinessException("上传文件类型不符，请上传扩展名为 doc, docx, pdf的有效合同文件。");
            }
            //检测上传的文件类型是否合格有效
            if (FileUtil.isChangeFileExtendType(filename, byteFileBlob)) {
                throw new BusinessException("上传文件类型不符，您可能手动修改过文件扩展名。请上传扩展名为 doc, docx, pdf的有效合同文件。");
            }
        }
    }
    private boolean checkIsExistConNo(String docNo){
        return baseMapper.selectCount(new LambdaQueryWrapper<Contract>().eq(Contract::getConNo, docNo).ne(Contract::getStatus, ConStatusEnum.CANCEL.getValue())) > 0;
    }
    public void updateById(ConUpdateReq updateReq) {
        if (YesOrNoEnum.YES.getValue().equals(updateReq.getHasPeriod())
                && (Objects.isNull(updateReq.getBeginPeriodTime()) || Objects.isNull(updateReq.getEndPeriodTime()))){
            throw new WarningException("固定期限合同,期限开始时间与结束时间不能为空");
        }
        Contract contract = getConByIdForUpdate(updateReq.getId());
        if (!ConStatusEnum.DRAFT.getValue().equals(contract.getStatus()) && !ConStatusEnum.AUDIT.getValue().equals(contract.getStatus())){
            throw new WarningException("只有起草中、审核中合同可修改");
        }
        CglibBeanCopierUtil.copy(updateReq, contract);
        contract.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(contract);
    }

    @Transactional
    public void changeConFile(Long id, MultipartFile docFile) {
        Contract contract = getConByIdForUpdate(id);
        AssertUtil.isEquals(ConStatusEnum.DRAFT.getValue(), contract.getStatus(), "只有起草中状态合同可更换文件");
        contract.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(contract);

        //更换合同文件
        conFileService.updateConFileByUploadFile(id, docFile);
        //添加合同动态
        conActivityNoteService.addSysNote(id, "更换了合同文件");
    }

    @Transactional
    public void changeConTemplate(Long id, Long templateId) {
        Contract contract = getConByIdForUpdate(id);
        AssertUtil.isEquals(ConStatusEnum.DRAFT.getValue(), contract.getStatus(), "只有起草中状态合同可更换文件");
        contract.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(contract);

        conFileService.updateConFileByTemplateId(contract.getId(), templateId);

        //添加合同动态
        conActivityNoteService.addSysNote(id, "更换了合同模板");
    }

    @Transactional
    public void draftComplete(Long id) {
        Contract contract = getConByIdForUpdate(id);
        AssertUtil.isEquals(ConStatusEnum.DRAFT.getValue(), contract.getStatus(), "合同状态错误");
        contract.setStatus(ConStatusEnum.AUDIT.getValue());
        contract.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(contract);
        conActivityNoteService.addSysNote(id, "起草完毕进入审核中");
    }

}
